#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <vector>
#include "gc_ptr.h"
#include "go.h"
#include "taginfo.h"
#include <list>
#include "boxing2.h"



struct llist
{
	int val;
	gc_ptr<llist> next;

	llist ()
	{
		val = 0;
		next = 0;
	}

	llist (int v)
	{
		val = v;
		next = 0;
	}
};

void add (gc_ptr<llist> &head, gc_ptr<llist> elem, gc_ptr<llist> cur)
{
	if (head == 0)
	{
		head = elem;
		return;
	}
	if (cur->next == NULL)
	{
		cur->next = elem;
	}
	else 
		add (head, elem, cur->next);
}

void print (gc_ptr<llist> cur)
{
	if (cur == 0)
		return;
//	printf("%d\n", (*cur).val);
	print(cur->next);
}

std::vector <void *> v;
std::map <void *, void*> mm;


void test (int STEP_COUNT, int ELEM_COUNT)
{
	std::list <size_t> llist1;
	llist1.push_front(64);
	for (int i = 0; i < STEP_COUNT; i++)
	{
		gc_ptr<llist> head;
		head = 0;
		for (int j = 0; j < ELEM_COUNT; j++)
		{
		  printf ("j = %d\n", j);
		  gc_ptr<llist> nw; 
		  nw = new llist(j);
		  void *tmp = nw.ptr;
//		  tmp = tmp - sizeof(void *);
		  void*tmp2;
		  mm[tmp] = tmp2 = generic_box_struct(llist1);
		  v.push_back (mm[tmp]);
		  add(head, nw, head);
		printf ("obj = %p\n", nw.ptr);
		printf ("gen_return = %p\n", tmp2);
		}
//		print(head);
		printf ("head = %p\n", head.ptr);
		for (ptr_list *l = collect(); l != 0; l = l->next)
		{
			printf ("root = %p\n", l->ptr);
			go(l->ptr, 1);
		}
		for (size_t i = 0; i < v.size(); i++)
			assert ((*((BLOCK_TAG *)v[i])).mbit == 1);	  

	}

	

}

int main (int argc, char *argv[])
{
	assert(argc == 3);
	int STEP_COUNT, ELEM_COUNT;
	sscanf (argv[1], "%d", &STEP_COUNT);
	sscanf (argv[2], "%d", &ELEM_COUNT);

	test(STEP_COUNT, ELEM_COUNT);

	return 0;
}
